const express = require('express')
const app = express()
const utils = require('../utils')
const bodyParser = require('body-parser')
const ResultVo = require('../vo/ResultVo')
const { verify } = require('../authorization/util-token')
const { tokenIsValid } = require('../authorization/util-time')
const HttpStatus = require('../vo/HttpStatus')
const { isExitUsername } = require('../authorization/db-ope')

/**
 * 是否关闭token
 * 判断某个controller的函数是否需要token
 * 默认全部都需要
 *              /   funName1 (api) true 需要检查
 * child配置优先 --- funName2 (api) true 需要检查
 *              \   funName3 (api) 默认需要token检查
 *
 *                         / true 不需要检查
 * global Controller全局配置
 *                         \ false/undefined 需要检查
 *
 * @param {*} funName 接口名称
 * @param {*} controller 类
 */
function isCloseToken(funName, controller) {
  let globalCloseToken = controller.globalCloseToken
  let childCloseToken = controller.childCloseToken
  if (childCloseToken && childCloseToken.length) {
    return childCloseToken.includes(funName)
  }
  return !!globalCloseToken
}

/**
 *
 * @param {*} ogisticServiceData
 * ogisticServiceData { dbClient, router, ResultVo }
 */
function apiServer(ogisticServiceData) {
  const { router, ResultVo } = ogisticServiceData
  const port = parseInt(process.env.AUTO_DEPLAY_ENV_PORT)
  // 设置允许跨域访问该服务.
  app.all('*', function (req, res, next) {
    res.header('Access-Control-Allow-Origin', '*')
    res.header('Access-Control-Allow-Headers', 'Content-Type')
    res.header('Access-Control-Allow-Methods', '*')
    res.header('Content-Type', 'application/json;charset=utf-8')
    next()
  })
  app.use(bodyParser.json())
  app.use(bodyParser.urlencoded({ extended: false }))
  const routerReturnObj = {}
  router.forEach((item) => {
    const routerList = []
    for (const funName in item.controller) {
      const url = `${item.url}${utils.toLine(funName)}`
      const { customRequestType, requestVo, responseVo, desc } =
        item.controller[funName].prototype || {}
      if (customRequestType) {
        routerList.push({
          customRequestType,
          url,
          requestVo,
          responseVo,
          open: false,
          desc
        })
        app[customRequestType.toLocaleLowerCase()](url, (req, res) => {
          // 判断是否不需要token, true表示不需要
          let is = isCloseToken(funName, item.controller)
          if (is) {
            item.controller[funName](req, res, ogisticServiceData)
          } else {
            // 需要token则进行校验
            verify(req.headers.authorization, ogisticServiceData.authPrivateKey)
              .then((verRes) => {
                let { username, iat, exp } = verRes || {}
                // 用户是否存在
                isExitUsername(req, res, ogisticServiceData, username)
                  .then((exit) => {
                    // 用户存在
                    if (exit) {
                      if (iat && exp) {
                        let isValid = tokenIsValid(iat, exp)
                        if (isValid) {
                          item.controller[funName](req, res, ogisticServiceData)
                        } else {
                          // token过期
                          res.send(
                            ResultVo({
                              status: HttpStatus.tokenIsInvalid.code,
                              message: HttpStatus.tokenIsInvalid.message,
                              data: null
                            })
                          )
                        }
                      } else {
                        // 无效token
                        res.send(
                          ResultVo({
                            status: HttpStatus.tokenIsInvalid.code,
                            message: HttpStatus.tokenIsInvalid.message,
                            data: null
                          })
                        )
                      }
                    } else {
                      // 没有这个用户
                      res.send(
                        ResultVo({
                          status: HttpStatus.NonExistentUser.code,
                          message: HttpStatus.NonExistentUser.message,
                          data: null
                        })
                      )
                    }
                  })
                  .catch((err) => {
                    console.log('isExitUsername run fail!', err)
                    res.send(
                      ResultVo({
                        status: HttpStatus.TokenUnexpected.code,
                        message: HttpStatus.TokenUnexpected.message,
                        data: null
                      })
                    )
                  })
              })
              .catch((err) => {
                if (!err.type) {
                  console.log('api-server index verify fail!', err)
                  return
                }
                let type = err.type || ''
                let obj = type ? HttpStatus[type] : HttpStatus.TokenUnexpected
                res.send(
                  ResultVo({
                    status: obj.code,
                    message: obj.message,
                    data: null
                  })
                )
              })
          }
        })
      }
    }
    if (!routerReturnObj[item.controller.name]) {
      routerReturnObj[item.controller.name] = {}
    }
    routerReturnObj[item.controller.name].items = routerList
    if (item.controller.description) {
      routerReturnObj[item.controller.name].description =
        item.controller.description
    }
  })
  app.post('/auto-deplay/swigger-json', (req, res) => {
    res.send(
      ResultVo({
        status: 0,
        data: routerReturnObj
      })
    )
  })

  app.listen(port)
  console.log(`log: api服务启动，端口[${port}]`)
}

module.exports = apiServer
